package com.yonyou.iuap.uimeta.common.service.httpclient;

import com.alibaba.fastjson.JSONObject;
import com.yonyou.iuap.context.InvocationInfoProxy;
import com.yonyou.iuap.uimeta.common.consts.UiConst;
import com.yonyou.iuap.uimeta.common.itf.httpclient.MdfUiMetaUnifiedHttpClientItf;
import com.yonyou.iuap.yms.http.*;
import com.yonyoucloud.iuap.ucf.mdd.starter.ucg.openapi.isv.router.module.isvrequest.ISVRequest;
import com.yonyoucloud.iuap.ucf.mdd.starter.ucg.openapi.isv.router.module.isvrequest.ISVRequestBody;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: zhuyjh
 * @Date: 2024/5/16 14:16
 */
public class IsvMdfUiMetaUnifiedHttpClientServiceImpl implements MdfUiMetaUnifiedHttpClientItf {


    private static final Logger logger = LoggerFactory.getLogger(IsvMdfUiMetaUnifiedHttpClientServiceImpl.class);

    /**
     * 连接超时
     * 单位：ms
     */
    private static final int CONNECTION_TIMEOUT_DEFAULT = 30000;

    /**
     * 读取超时
     * 单位：ms
     */
    private static final int READ_TIMEOUT_DEFAULT = 30000;

    private static final String CONTENT_TYPE = "Content-Type";

    private final YmsHttpClient ymsHttpClient;

    @Autowired
    private ISVRequest isvRequest;

    public IsvMdfUiMetaUnifiedHttpClientServiceImpl(YmsHttpClient ymsHttpClient) {
        this.ymsHttpClient = ymsHttpClient;
    }

    @Override
    public String postUrl(String url, Object body, Map<String, String> headerMap) {
        return postUrl(url, body, headerMap, CONNECTION_TIMEOUT_DEFAULT, READ_TIMEOUT_DEFAULT);
    }

    @Override
    public String getUrl(String url, Map<String, Object> param, Map<String, String> headerMap) {
        return getUrl(url, param, headerMap, CONNECTION_TIMEOUT_DEFAULT, READ_TIMEOUT_DEFAULT);
    }

    @Override
    public String postUrl(String url, Object body, Map<String, String> headerMap, Integer requestTimeout, Integer readTimeout) {
        if (InvocationInfoProxy.getYhtAccessToken()!=null && !InvocationInfoProxy.getYhtAccessToken().startsWith("btt")) {
            ISVRequestBody isvRequestBody = new ISVRequestBody();
            isvRequestBody.setUrl(url);
            isvRequestBody.setRequestMethod("POSTJSON");
            HashMap<String, String> hashMap = new HashMap<>();
            hashMap.put("data", JSONObject.toJSONString(body));
            isvRequestBody.setParams(hashMap);
            String yhtAccessToken = InvocationInfoProxy.getYhtAccessToken();
            if(headerMap == null) {
                headerMap = new HashMap<>();
            }
            headerMap.put("yht_access_token", yhtAccessToken);
            isvRequestBody.setHeaders(headerMap);
            String result = isvRequest.doRequest(InvocationInfoProxy.getTenantid(), isvRequestBody);
            return result;
        }
        YmsHttpRequest request = buildYmsHttpRequest(url, null, headerMap, YmsHttpMethod.POST, requestTimeout, readTimeout, body);
        return getResponse(url, request);
    }

    @Override
    public String getUrl(String url, Map<String, Object> param, Map<String, String> headerMap, Integer requestTimeout, Integer readTimeout) {
        if (InvocationInfoProxy.getYhtAccessToken()!=null && !InvocationInfoProxy.getYhtAccessToken().startsWith("btt")) {
            ISVRequestBody isvRequestBody = new ISVRequestBody();
            String urlWithParam = appendParamsToUrl(url, param);
            isvRequestBody.setUrl(urlWithParam);
            isvRequestBody.setRequestMethod("GET");
            HashMap<String, String> paramsMap = new HashMap<>();
            isvRequestBody.setParams(null);
            String yhtAccessToken = InvocationInfoProxy.getYhtAccessToken();
            if(headerMap == null) {
                headerMap = new HashMap<>();
            }
            headerMap.put("yht_access_token", yhtAccessToken);
            isvRequestBody.setHeaders(headerMap);
            String result = isvRequest.doRequest(InvocationInfoProxy.getTenantid(), isvRequestBody);
            return result;
        }
        YmsHttpRequest request = buildYmsHttpRequest(url, param, headerMap, YmsHttpMethod.GET, null, null, null);
        return getResponse(url, request);
    }


    /**
     * 构建请求
     *
     * @param url
     * @param param
     * @param header
     * @param method
     * @param requestTimeout
     * @param readTimeout
     * @return
     */
    private YmsHttpRequest buildYmsHttpRequest(String url, Map<String, Object> param, Map<String, String> header, YmsHttpMethod method, Integer requestTimeout, Integer readTimeout, Object body) {
        YmsHttpRequestBuilder requestBuilder = getYmsHttpRequestBuilder(url, param, header, method, requestTimeout, readTimeout);
        if (YmsHttpMethod.POST.equals(method) && body != null) {
            requestBuilder.body(JSONObject.toJSONString(body));
        }
        return requestBuilder.build();
    }


    /**
     * 构建请求参数
     *
     * @param url
     * @param param
     * @param header
     * @param method
     * @param requestTimeout
     * @param readTimeout
     * @return
     */
    private YmsHttpRequestBuilder getYmsHttpRequestBuilder(String url, Map<String, Object> param, Map<String, String> header, YmsHttpMethod method, Integer requestTimeout, Integer readTimeout) {
        url = appendParamsToUrl(url, param);
        YmsHttpRequestBuilder requestBuilder = new YmsHttpRequestBuilder();
        if (requestTimeout == null) {
            requestTimeout = CONNECTION_TIMEOUT_DEFAULT;
        }
        if (readTimeout == null) {
            readTimeout = READ_TIMEOUT_DEFAULT;
        }
        requestBuilder.url(url).method(method).addHeader(buildCommonHeader(header)).requestTimeout(requestTimeout).readTimeout(readTimeout);
        return requestBuilder;
    }

    /**
     * 构建请求头
     *
     * @param headerMap
     * @return
     */
    private YmsHttpHeader buildCommonHeader(Map<String, String> headerMap) {
        YmsHttpHeader headers = new YmsHttpHeader();
        headers.add(CONTENT_TYPE, "application/json;charset=utf-8");
        if (MapUtils.isNotEmpty(headerMap)) {
            headerMap.forEach((key, value) -> headers.add(key, value));
        }
        return headers;
    }

    /**
     * 构建请求
     *
     * @param url
     * @param request
     * @return
     */
    private String getResponse(String url, YmsHttpRequest request) {
        try (YmsHttpResponse ymsHttpResponse = ymsHttpClient.execute(request)) {
            int statusCode = ymsHttpResponse.getStatusCode();
            if (statusCode == UiConst.Int.ER_BAI) {
                return ymsHttpResponse.getBodyString();
            } else {
                String message = ymsHttpResponse.getBodyString();
                throw new RuntimeException("Http请求：" + url + "失败，状态码：" + statusCode + ",返回信息：" + message);
            }
        } catch (Exception e) {
            throw new RuntimeException("Http请求：" + url + "，出现异常" + e.getMessage(), e);
        }
    }

    /**
     * 拼接url参数
     *
     * @param serverUrl url参数
     * @param paramMap  参数map
     * @return
     */
    private String appendParamsToUrl(String serverUrl, Map<String, Object> paramMap) {
        try {
            if (StringUtils.isEmpty(serverUrl)) {
                throw new IllegalArgumentException("请求URL不可为空！");
            }
            StringBuilder stringBuilder = new StringBuilder(serverUrl);
            if (MapUtils.isEmpty(paramMap)) {
                return stringBuilder.toString();
            }
            if (serverUrl.contains("?")) {
                stringBuilder.append("&");
            } else {
                stringBuilder.append("?");
            }
            for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
                String inputName = entry.getKey();
                Object inputValueObj = entry.getValue();
                if (inputValueObj == null) {
                    continue;
                }
                String inputValue = String.valueOf(inputValueObj);
                stringBuilder.append(URLEncoder.encode(inputName, UiConst.Str.UTF8));
                stringBuilder.append("=");
                stringBuilder.append(URLEncoder.encode(inputValue, UiConst.Str.UTF8));
                stringBuilder.append("&");
            }
            stringBuilder.append("little_mod_ts");
            stringBuilder.append("=");
            stringBuilder.append(System.currentTimeMillis());
            return stringBuilder.toString();
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException("封装参数：%s到请求地址：" + serverUrl + "，时出现异常：" + e.getMessage(), e);
        }

    }
}